# -*- coding: utf-8 -*-
"""
Created on Fri Oct  8 19:15:46 2021

@author: 刘长奇
"""
#本算法设置3个隐藏节点

# moon dataset

import numpy as np
from sklearn import datasets
import matplotlib.pyplot as plt
import random
from sklearn.metrics import confusion_matrix
import seaborn as sns

# generate sample data
np.random.seed(0)
data, target = datasets.make_moons(200, noise=0.20)

def sigmoid(x):
    return 1/(1+np.exp(-x))

#权值更新函数
def weight(true,estimate,z):
    t1=estimate-true
    t2=estimate*(1-estimate)
    return t1*t2*z

#误分类下标记录函数
def error_note(target,label):
    note=[]
    for i in range(np.shape(target)[0]):
        if target[i]!=label[i]:
            note.append(i)
    return note

size=500  #迭代次数为500次


#针对0进行分类，剩下的顺理成章就是1
label_0=[]
class_0=[]
label_arg=[]   #记录0下标
theta=0.01
for i in range(np.shape(target)[0]):
    if target[i]==0:
        label_0.append(0)
        label_arg.append(i)

#标签0数据提取
data_0=[]
for i in range(len(label_arg)):
    data_0.append(data[label_0[i]])
data_0=np.array(data_0)
    
#开始分类
w1=np.array([[0.1,0.2,0.3],[0.4,0.5,0.6]])  #从输入层到隐藏层的权重
w2=np.array([[0.1,0.2],[0.3,0.4],[0.5,0.6]])  #从隐藏层到输出层的权重
y=np.zeros(2)
n=np.shape(data_0)[0]
for j in range(size):
    class_0=[]
    z=[]   #用于储存隐藏层结果
    #前向计算
    for i in range(n):
        y=np.matrix(data_0[i])*np.matrix(w1)*np.matrix(w2)
        y=np.array(y)
        y[0,0]=sigmoid(y[0,0])
        y[0,1]=sigmoid(y[0,1])
        if y[0,0]>=y[0,1]:
            class_0.append(0)
        else:
            class_0.append(1)
    
    #后向计算：随机梯度下降法
    temp=error_note(label_0,class_0)
    if len(temp)==0:
        break
    q=random.randint(0,len(temp)-1)
    for i in range(np.shape(w1)[1]):
        z.append(np.matrix(data_0[i])*np.matrix(np.array([[w1[0,i]],[w1[1,i]]])))
    
    
    for i in range(np.shape(w2)[0]):
        
        w2[i,0]=w2[i,0]-(y[0,0]-0.9)*y[0,0]*(1-y[0,0])*z[i]*theta
        w2[i,1]=w2[i,1]-(y[0,1]-0.1)*y[0,1]*(1-y[0,1])*z[i]*theta
        w1[0,i]=w1[0,i]-(y[0,0]-0.9)*y[0,0]*(1-y[0,0])*z[i]*data_0[i,0]*theta
        w1[1,i]=w1[1,i]-(y[0,0]-0.9)*y[0,0]*(1-y[0,0])*z[i]*data_0[i,1]*theta
result=np.ones(np.shape(data)[0])

for i in range(np.shape(data)[0]):
        y=np.matrix(data[i])*np.matrix(w1)*np.matrix(w2)
        y=np.array(y)
        y[0,0]=sigmoid(y[0,0])
        y[0,1]=sigmoid(y[0,1])
        if y[0,0]<=y[0,1]:
            result[i]=0
        else:
            result[i]=1
#计算分类准确度    
j=0
for i in range(np.shape(data)[0]):
    if result[i]==target[i]:
        j=j+1
print('准确率为：',j/np.shape(data)[0])    #结果为0.82

confusion_matrix_result=confusion_matrix(result,target)
# plot data
plt.subplot(1,2,1)
plt.title('initial data')
plt.scatter(data[:, 0], data[:, 1], c=target, cmap=plt.cm.Spectral)
plt.subplot(1,2,2)
plt.title('nets result')
plt.scatter(data[:, 0], data[:, 1], c=result, cmap=plt.cm.Spectral)
plt.colorbar()

#错误数据可视化

plt.figure(figsize=(8,6))
sns.heatmap(confusion_matrix_result,annot=True,cmap='Blues')
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.title('confusion_matrix')
plt.show()















